--万年历菜单模块
--201841052073 叶佳豪
--**************引入库********************
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
--**************声明实体区*****************
-- 数码管5 23 downto 20
-- 数码管4 19 downto 16
-- 数码管3 15 downto 12
-- 数码管2 11 downto 8
-- 数码管1 7 downto 4
-- 数码管0 3 downto 0
--5做为最左边
ENTITY CalendarMenu IS										
	PORT(		RTC_Time_IN				:IN std_logic_vector(23 downto 0);	--时分秒输入 （2+2+2）*4
				RTC_Date_IN				:IN std_logic_vector(31 downto 0);	--年月日输入（4+2+2）*4
				RTC_WeekDay_IN			:IN std_logic_vector(3 downto 0);	--周几输入
				SET_Time_IN				:IN std_logic_vector(23 downto 0);	--设置时分秒输入 （2+2+2）*4
				KEY0_IN					:IN std_logic;						--换页按键 默认0 响应1
				KEY1_IN,KEY2_IN,KEY3_IN	:IN std_logic;						--功能按键 默认0 响应1
				CLK1Hz,CLK1KHz			:IN std_logic;						--菜单时钟1KHz
				DataChange				:OUT std_logic_vector(8 downto 0);	--调整控制输出 8..6年月日 5..3时分秒 2..0闹钟时分秒
				Display_OUT				:OUT std_logic_vector(23 downto 0):= "000000000000000000000000";	--数码管显示数据输出 6*4
				Buzzer_OUT				:OUT std_logic			--蜂鸣器输出
		);
END CalendarMenu;
--***************结构体区****************		
ARCHITECTURE RUN OF CalendarMenu IS
SIGNAL PageNum		:integer range 0 to 4 := 0;			--当前页码 范围0-3 默认0
SIGNAL ChNum		:integer range 0 to 3 := 0;			--当前改的参数 范围0-2 默认0
SIGNAL BuzzerStatus	:integer range 0 to 3 := 0;			--当前蜂鸣器状态 范围0-3 默认0
SIGNAL BuzzerTime 	:integer range 0 to 50000000 := 0;

BEGIN
P_Menu:PROCESS(CLK1Hz,KEY0_IN,KEY1_IN,KEY2_IN)
	BEGIN
		IF CLK1Hz'EVENT AND CLK1Hz = '1' THEN--1S
		DataChange<="000000000";
			IF KEY0_IN = '1' THEN		--翻页键
				PageNum <= PageNum + 1;
				IF BuzzerStatus = 2 THEN BuzzerStatus <= 0;ELSE BuzzerStatus<=2;END IF;		--控制蜂鸣器响一下
				IF PageNum >= 3 THEN	PageNum <= 0;END IF;--限幅
				ChNum <= 0;--复位改参
				
			ELSIF KEY1_IN = '1' THEN			--进入改参模式
				CASE PageNum IS					--根据所在的页面来改
					WHEN 0 => --调整时钟
						IF KEY2_IN = '1' THEN		--更换改参的位数
							ChNum <= ChNum + 1;
							IF BuzzerStatus = 2 THEN BuzzerStatus <= 0;ELSE BuzzerStatus<=2;END IF;		--不是循环响的模式就清零		--响一下
							IF ChNum > 3 THEN	ChNum <= 0;END IF;--限幅
						END IF;
						CASE ChNum IS
							WHEN 0 => IF KEY3_IN = '1' THEN	DataChange(3)<='1';ELSE DataChange(3)<='0';END IF;		--0 改秒
							WHEN 1 => IF KEY3_IN = '1' THEN	DataChange(4)<='1';ELSE DataChange(4)<='0';END IF;		--1 改分
							WHEN 2 => IF KEY3_IN = '1' THEN	DataChange(5)<='1';ELSE DataChange(5)<='0';END IF;		--2 改时
							WHEN OTHERS=>NULL;
						END CASE;
					
					WHEN 1 => --调整日期
						IF KEY2_IN = '1' THEN		--更换改参的位数
							ChNum <= ChNum + 1;
							IF BuzzerStatus = 2 THEN BuzzerStatus <= 0;ELSE BuzzerStatus<=2;END IF;		--不是循环响的模式就清零		--响一下
							IF ChNum > 3 THEN	ChNum <= 0;END IF;--限幅
						END IF;
						CASE ChNum IS
							WHEN 0 => IF KEY3_IN = '1' THEN	DataChange(6)<='1';ELSE DataChange(6)<='0';END IF;		--0 改日
							WHEN 1 => IF KEY3_IN = '1' THEN	DataChange(7)<='1';ELSE DataChange(7)<='0';END IF;		--1 改月
							WHEN OTHERS=>NULL;
						END CASE;
					
					WHEN 2 => --调整年份
						IF KEY3_IN = '1' THEN	DataChange(8)<='1';ELSE DataChange(8)<='0';END IF;		--0 改年
					
					WHEN 3 => --调整闹钟
						IF KEY2_IN = '1' THEN		--更换改参的位数
							ChNum <= ChNum + 1;
							IF BuzzerStatus = 2 THEN BuzzerStatus <= 0;ELSE BuzzerStatus<=2;END IF;		--不是循环响的模式就清零		--响一下
							IF ChNum > 3 THEN	ChNum <= 0;END IF;--限幅
						END IF;
						CASE ChNum IS
							WHEN 0 => IF KEY3_IN = '1' THEN	DataChange(1)<='1';ELSE DataChange(1)<='0';END IF;		--0 改分
							WHEN 1 => IF KEY3_IN = '1' THEN	DataChange(2)<='1';ELSE DataChange(2)<='0';END IF;		--1 改时
							WHEN OTHERS=>NULL;
						END CASE;
					
					WHEN OTHERS=>NULL;
				END CASE;
			ELSIF RTC_Time_IN(23 downto 8)=SET_Time_IN(23 downto 8) THEN			--进入闹钟模式
					BuzzerStatus<=3;
			ELSIF RTC_Time_IN(15 downto 0)="0000000000000000" THEN			--进入报时模式
					BuzzerStatus<=1;
			ELSE BuzzerStatus<=0;
			END IF;
			
		END IF;
END PROCESS;

P_BuzzerControl:PROCESS(CLK1KHz,BuzzerStatus)	--根据状态来控制蜂鸣器
	BEGIN
		IF CLK1KHz'EVENT AND CLK1KHz = '1' THEN
			CASE BuzzerStatus IS
			WHEN 0 => Buzzer_OUT <= '0';BuzzerTime <=0;		--0 不响
			WHEN 1 => Buzzer_OUT <= '1';					--1 一直响
			WHEN 2 => IF BuzzerTime <= 30 THEN Buzzer_OUT <= '1';BuzzerTime <= BuzzerTime + 1;ELSE Buzzer_OUT <= '0'; END IF;--响一下
			WHEN 3 => IF BuzzerTime <= 100 THEN Buzzer_OUT <= '1';BuzzerTime <= BuzzerTime + 1;ELSIF BuzzerTime=200 THEN Buzzer_OUT <= '0';BuzzerTime <=0;ELSE Buzzer_OUT <= '0';BuzzerTime <= BuzzerTime + 1; END IF;--循环响 闹钟
			WHEN OTHERS=>NULL;
		END CASE;
		END IF;
END PROCESS;
P_DisplayPage:PROCESS(PageNum,RTC_Time_IN,RTC_WeekDay_IN,SET_Time_IN)--页码 时间 日期 设置时间改变就刷新
	BEGIN
		CASE PageNum IS
			WHEN 0 => Display_OUT <= RTC_Time_IN;		--0 时钟
			WHEN 1 => Display_OUT(23 downto 20) <= RTC_WeekDay_IN;Display_OUT(19 downto 16) <= "1100";Display_OUT(15 downto 0) <= RTC_Date_IN(15 downto 0);	--1 星期 日期 
			WHEN 2 => Display_OUT(23 downto 16) <= "11001100"; Display_OUT(15 downto 0) <= RTC_Date_IN(31 downto 16);	--2 年 不显示的管子熄屏
			WHEN 3 => Display_OUT <= SET_Time_IN;								--3 闹钟
			WHEN OTHERS=>NULL;
		END CASE;
END PROCESS;
end RUN;
--****************************************

